package com.gzhryc.common.gps;

import com.gzhryc.common.logging.Logger;

import java.util.ArrayList;
import java.util.List;

public class GPSLocationService {

    static Logger log = Logger.getLogger(GPSLocationService.class);

    private double EARTH_RADIUS = 6378.137;

    private final IGPSDataService gpsDataService;

    public GPSLocationService(IGPSDataService gpsDataService){
        this.gpsDataService = gpsDataService;
    }

    public List<GPSDistance> findByGPS(Double lat1, Double lng1,Integer limit){
        if(this.gpsDataService != null && lng1 != null && lat1 != null && limit != null) {
            List<GPSEntity> gpsEntityList = this.gpsDataService.getList();
            if(gpsEntityList != null && gpsEntityList.size() > 0) {
                List<GPSDistance> result = new ArrayList<>();
                for (GPSEntity gpsEntity : gpsEntityList) {
                    Double distance = getDistance(lat1, lng1, gpsEntity.getLatitude(), gpsEntity.getLongitude());
                    if(result.size() == 0){
                        GPSDistance gpsDistance = new GPSDistance();
                        gpsDistance.setId(gpsEntity.getId());
                        gpsDistance.setDistance(distance);
                        result.add(gpsDistance);
                    }else {
                        boolean flag = result.size() < limit;
                        for (int i = 0; i < result.size(); i++) {
                            GPSDistance item = result.get(i);
                            if(item.getDistance() < distance){
                                GPSDistance gpsDistance = new GPSDistance();
                                gpsDistance.setId(gpsEntity.getId());
                                gpsDistance.setDistance(distance);
                                result.add(i,gpsDistance);
                                flag = false;
                                break;
                            }
                        }

                        if(flag){
                            GPSDistance gpsDistance = new GPSDistance();
                            gpsDistance.setId(gpsEntity.getId());
                            gpsDistance.setDistance(distance);
                            result.add(gpsDistance);
                        }
                    }
                }
                return result;
            }
        }else {
            log.error("GPS数据服务不存在或参数错误");
        }
        return null;
    }

    public List<GPSDistance> findByGPS(Double lat1, Double lng1,Double limitDistance,Integer limit){
        if(this.gpsDataService != null && lng1 != null && lat1 != null && limitDistance != null && limit != null) {
            List<GPSEntity> gpsEntityList = this.gpsDataService.getList();
            if(gpsEntityList != null && gpsEntityList.size() > 0) {
                List<GPSDistance> result = new ArrayList<>();
                for (GPSEntity gpsEntity : gpsEntityList) {
                    Double distance = getDistance(lat1, lng1, gpsEntity.getLatitude(), gpsEntity.getLongitude());
                    if(distance > limitDistance){
                        continue;
                    }
                    if(result.size() == 0){
                        GPSDistance gpsDistance = new GPSDistance();
                        gpsDistance.setId(gpsEntity.getId());
                        gpsDistance.setDistance(distance);
                        result.add(gpsDistance);
                    }else {
                        boolean flag = result.size() < limit;
                        for (int i = 0; i < result.size(); i++) {
                            GPSDistance item = result.get(i);
                            if(item.getDistance() < distance){
                                GPSDistance gpsDistance = new GPSDistance();
                                gpsDistance.setId(gpsEntity.getId());
                                gpsDistance.setDistance(distance);
                                result.add(i,gpsDistance);
                                flag = false;
                                break;
                            }
                        }

                        if(flag){
                            GPSDistance gpsDistance = new GPSDistance();
                            gpsDistance.setId(gpsEntity.getId());
                            gpsDistance.setDistance(distance);
                            result.add(gpsDistance);
                        }
                    }
                }
                return result;
            }
        }else {
            log.error("GPS数据服务不存在或参数错误");
        }
        return null;
    }

    public List<GPSDistance> findByGPS(Double lat1, Double lng1,List<Long> ids){
        if(this.gpsDataService != null && lng1 != null && lat1 != null && ids != null && ids.size() > 0) {
            List<GPSDistance> result = new ArrayList<>();
            for(Long id : ids){
                boolean flag = true;
                Double distance = null;
                GPSEntity gpsEntity = this.gpsDataService.getById(id);
                if(gpsEntity != null) {
                    distance = getDistance(lat1, lng1, gpsEntity.getLatitude(), gpsEntity.getLongitude());
                    for (int i = 0; i < result.size(); i++) {
                        GPSDistance item = result.get(i);
                        //空距离排最后
                        if(item.getDistance() == null || item.getDistance() < distance){
                            GPSDistance gpsDistance = new GPSDistance();
                            gpsDistance.setId(id);
                            gpsDistance.setDistance(distance);
                            result.add(i,gpsDistance);
                            flag = false;
                            break;
                        }
                    }
                }

                if(flag){
                    GPSDistance gpsDistance = new GPSDistance();
                    gpsDistance.setId(id);
                    gpsDistance.setDistance(distance);
                    result.add(gpsDistance);
                }
            }
            return result;
        }else {
            log.error("GPS数据服务不存在或参数错误");
        }
        return null;
    }

    /**
     * 根据两个位置的经纬度，来计算两地的距离（单位为M）
     *
     * @param lat1 当前经度
     * @param lng1 当前纬度
     * @param lat2 目标经度
     * @param lng2 目标纬度
     * @return 距离
     */
    public Double getDistance(Double lat1, Double lng1, Double lat2, Double lng2) {
        if (lat1 != null && lng1 != null && lat2 != null && lng2 != null) {
            double radLat1 = rad(lat1);
            double radLat2 = rad(lat2);
            double difference = radLat1 - radLat2;
            double mdifference = rad(lng1) - rad(lng2);
            double distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(difference / 2), 2)
                    + Math.cos(radLat1) * Math.cos(radLat2)
                    * Math.pow(Math.sin(mdifference / 2), 2)));
            distance = distance * EARTH_RADIUS;
            distance = Math.round(distance * 1000);
            return distance;
        }
        return 0.0;
    }

    private double rad(double d) {
        return d * Math.PI / 180.0;
    }
}
